package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.entity.Employee;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/*
 * 切面类：
 *      切入点表达式：annotation定位需要增强的方法
 *      通知方法：公告的操作，前置通知/环绕
 * */
@Component
@Aspect
public class AutoFillAspect {
    @Before("@annotation(com.sky.annotation.AutoFill)")
    public void autoFillField(JoinPoint jp) throws Exception {
        System.out.println("填充公告的字段");

        //1.获取目标方法的第一个参数实体对象
        Object entity = jp.getArgs()[0];

        //2.给其设置公告属性：4/2
        MethodSignature signature = (MethodSignature) jp.getSignature();
        Method methodObj = signature.getMethod();
        AutoFill annotation = methodObj.getAnnotation(AutoFill.class);
        //2.1判断当前是否是添加操作，设置公告属性：createTime/createUser/updateTime/updateUser
        Class<?> aClass = entity.getClass();
        if (annotation.value().equals(OperationType.INSERT)) {
            //如何给entity设置四个属性：反射技术
            Field createTimeFileld =aClass.getDeclaredField(AutoFillConstant.CREATE_TIME);
            createTimeFileld.setAccessible(true);//暴力访问
            createTimeFileld.set(entity,LocalDateTime.now());

            Field createUserFileld =aClass.getDeclaredField(AutoFillConstant.CREATE_USER);
            createUserFileld.setAccessible(true);//暴力访问
            createUserFileld.set(entity,BaseContext.getCurrentId());

            Field updateTimeField =aClass.getDeclaredField(AutoFillConstant.UPDATE_TIME);
            updateTimeField.setAccessible(true);//暴力访问
            updateTimeField.set(entity,LocalDateTime.now());

            Field updateUserField =aClass.getDeclaredField(AutoFillConstant.UPDATE_USER);
            updateUserField.setAccessible(true);//暴力访问
            updateUserField.set(entity,BaseContext.getCurrentId());
        }
        //2.2判断当前是否是更新操作，设置公告属性：updateTime/updateUser
        else {
            //如何给entity设置两个属性：反射技术

            Field updateTimeField =aClass.getDeclaredField(AutoFillConstant.UPDATE_TIME);
            updateTimeField.setAccessible(true);//暴力访问
            updateTimeField.set(entity,LocalDateTime.now());

            Field updateUserField =aClass.getDeclaredField(AutoFillConstant.UPDATE_USER);
            updateUserField.setAccessible(true);//暴力访问
            updateUserField.set(entity, BaseContext.getCurrentId());
        }
    }

    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 反射的一切操作的源头：字节码对象（Employee.class字节码文件---ClaLoader类加载器----内存：）
        Employee employee = new Employee();
        Class<? extends Employee> employeeClass = employee.getClass();

        /*Field createTime = employeeClass.getDeclaredField("createTime");*/

        Method setCreateTimeMethod = employeeClass.getDeclaredMethod("setCreateTime", LocalDateTime.class);//获取设置属性的方法对象
        setCreateTimeMethod.invoke(employee,LocalDateTime.now());
        System.out.println(employee);

    }
}